home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
fg
/
fgl402b
/
manuals.arj
/
USER10.DOC
< prev
next >
Wrap
Text File
|
1995-02-06
|
102KB
|
2,376 lines
Chapter 10
Bitmapped Images
212 Fastgraph User's Guide
Overview
In this chapter, we'll continue our discussion of images by concentrating
on an important class of images called bitmapped images. Fastgraph includes
routines to display, retrieve, and manipulate bitmapped images in mode-
specific and mode-independent formats. This chapter will discuss the Fastgraph
routines that deal with both classes of bitmapped images.
Displaying bitmapped images is an essential part of animation with
Fastgraph. While the image files discussed in the previous chapter are useful
for displaying backgrounds or importing pictures from other sources, an
animation sequence can only achieve its speed through the bitmapped image
display routines described in this chapter, along with the block transfer
routines of the next chapter.
Mode-Independent Bitmapped Images
This section will discuss the image display routines that use the same
bitmapped image format for all graphics video modes. Another class of
routines, described in the next section, use different formats for different
video modes. While these mode-independent image display routines are more
general, they achieve this generality at the sake of execution speed. This may
especially be a concern if the image is large, or if speed is critical in an
application (as in arcade-style graphics). For many programs, however, the
mode-independent routines provide all the image display capability needed.
Let's begin by returning to an example of a very simple image -- the
triangle introduced in the previous chapter:
. . . . * . . . .
. . . * x * . . .
. . * x x x * . .
. * x x x x x * .
* * * * * * * * *
Recall that the triangle's perimeter is a different color than its interior
pixels, and to use this image with Fastgraph, we must inscribe the triangle in
a rectangular area. As before, our triangle is nine pixels wide at its base
and five pixels high. The pixels indicated by an asterisk (*) are the
triangle's perimeter, while those indicated by an x represent its interior
points. We need to distinguish between these pixels because they will be
different colors. The pixels shown as periods (.) are not part of the triangle
itself. They are required to make the image rectangular, so from Fastgraph's
perspective they are indeed part of the image.
The Fastgraph routine fg_drawmap is a suitable routine for drawing our
triangle. To use fg_drawmap, we must create separate bitmaps for each color in
the image (excluding the points used to fill the rectangular region, which are
considered transparent). In this example, we will thus need two bitmaps -- one
for the perimeter points, and one for the interior points. Let's break the
image into these two bitmaps.
Chapter 10: Bitmapped Images 213
. . . . * . . . . . . . . . . . . .
. . . * . * . . . . . . . x . . . .
. . * . . . * . . . . . x x x . . .
. * . . . . . * . . . x x x x x . .
* * * * * * * * * . . . . . . . . .
perimeter points interior points
The next step is to convert these two bitmaps into their binary
representations. Just as there are eight bits in a byte, we will create a data
structure (an array in this case) with each byte holding eight pixels. Bits
that are set (1) indicate the corresponding pixel will appear displayed in the
color associated with that bitmap. Bits that are reset (0) leave the
corresponding pixel unchanged. The size of each bitmap array must be at least
10 bytes because each bitmap contains five rows with nine pixels in each row
(that is, two bytes are required for each row of the image). Hence, when we
convert these bitmaps to their binary representations, and subsequently to
their hexadecimal equivalent, the results will appear as shown here. The
boldface bits represent the actual image; the other bits are filler bits
needed to complete each row of the bitmaps after the ninth pixel. All filler
bits must be zero.
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 08 00
0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 14 00
0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 22 00
0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 41 00
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 FF 80
perimeter bitmap
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 00
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 08 00
0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 1C 00
0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 3E 00
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 00
interior bitmap
The next matter is the order in which the bitmaps are stored in the
corresponding data structures. Since our data structure is an array, it is
only necessary to show the relationship of the subscripts to the bitmap
structures above. The next diagram shows the subscript order for the case of a
two-column by five-row bitmap.
[8] [9]
214 Fastgraph User's Guide
[6] [7]
[4] [5]
[2] [3]
[0] [1]
From this diagram, we see the first element of the array (that is, the
element with subscript [0]) represents the lower left corner of the image. The
subscript progression then continues right until reaching the end of the first
row. It then resumes at the leftmost element of the second row and continues
to the right until the end of that row. It continues in this manner for all
remaining rows.
We are now ready to present an example program to display our triangle.
The program will use the Fastgraph routine fg_drawmap, which expects three
arguments. The first argument is the bitmap array (passed by reference), the
second is the width of the bitmap in bytes, and the last is the height of the
bitmap in pixel rows. The fg_drawmap routine displays the image such that its
lower left corner is at the graphics cursor position on the active video page.
The routine has no effect in text video modes. Additionally, fg_drawmap
displays the image using the current color index, which means we will need to
call fg_drawmap once for each color in the image.
Example 10-1 runs in any 320x200 color graphics mode (it could be made to
run in mode 12 too, but that would detract from the purpose of the example).
After establishing the video mode, the program uses fg_rect to fill the entire
screen with a gray rectangle (white in CGA). Next, the program establishes
(156,101) as the graphics cursor position; this causes the triangle to be
centered on the screen. The two calls to fg_drawmap, one for each color in the
image, actually display the triangle. Note especially how fg_setcolor is used
before each call to fg_drawmap to define the current color index. The result
is a triangle with a blue perimeter (cyan in CGA) and green interior (magenta
in CGA).
Example 10-1.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char perimeter[] = {
0xFF,0x80,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00
};
char interior[] = {
0x00,0x00,0x3E,0x00,0x1C,0x00,0x08,0x00,0x00,0x00
};
void main()
{
int old_mode, new_mode;
Chapter 10: Bitmapped Images 215
fg_initpm();
new_mode = fg_bestmode(320,200,1);
if (new_mode < 0 || new_mode == 12) {
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
fg_setcolor(7);
fg_rect(0,319,0,199);
fg_move(156,101);
fg_setcolor(1);
fg_drawmap(perimeter,2,5);
fg_setcolor(2);
fg_drawmap(interior,2,5);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
We should mention that fg_drawmap does not perform clipping when
displaying an image. If you want the image to be constrained by the current
clipping limits, use fg_clipmap instead of fg_drawmap. The fg_clipmap routine
takes the same three arguments as fg_drawmap, but it is not as fast as
fg_drawmap because of the additional overhead required when performing the
image clipping.
The different color bitmaps used by fg_drawmap do not all have to be the
same size. In our triangle example, the perimeter is 9 pixels wide by 5 pixels
high, but the interior is only 5 pixels wide by 3 pixels high. Hence, the
bitmap for the interior pixels only requires one byte for each of its three
rows, so we can store it in a three-byte array. Its structure would be:
[2] 08
[1] 1C
[0] 3E
Example 10-2 is similar to example 10-1, but it uses a three-byte array
for the interior bitmap. Note the second call to fg_move in this example. It
is needed because the bottom row of the smaller interior bitmap corresponds to
the second row of the larger perimeter bitmap. In other words, the interior
bitmap must be displayed one row above the perimeter bitmap.
Example 10-2.
#include <fastgraf.h>
216 Fastgraph User's Guide
#include <stdio.h>
#include <stdlib.h>
void main(void);
char perimeter[] = {
0xFF,0x80,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00
};
char interior[] = {
0x3E,0x1C,0x08
};
void main()
{
int old_mode, new_mode;
fg_initpm();
new_mode = fg_bestmode(320,200,1);
if (new_mode < 0 || new_mode == 12) {
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
fg_setcolor(7);
fg_rect(0,319,0,199);
fg_move(156,101);
fg_setcolor(1);
fg_drawmap(perimeter,2,5);
fg_move(156,100);
fg_setcolor(2);
fg_drawmap(interior,1,3);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
In example 10-2, the time required to execute the second call to fg_move
may not be worth the saving of 7 bytes. When array space is critical, or when
the images are larger, the use of smaller bitmaps for certain colors may be
more valuable.
Yet another possibility for example 10-2 would be to shift the elements
of the interior bitmap two pixels to the left. In this way, the bitmap would
be aligned against the left side of the array, as the perimeter bitmap is. The
three values comprising the interior bitmap would then become F8, 70, and 20.
We also would need to change the x coordinate in the second call to fg_move
from 156 to 158.
Chapter 10: Bitmapped Images 217
Mode-Specific Bitmapped Images
This section will discuss the image display routines that use bitmapped
image formats specific to each text and graphics video mode. The different
image formats closely resemble the structure of video memory in each mode, so
these routines are much faster than displaying mode-independent bitmaps with
fg_drawmap. If you use the mode-specific bitmaps in a program that supports
several video modes, there will be some additional programming that is not
needed when using mode-independent bitmaps. Usually, however, your efforts
will be rewarded with significantly faster graphics.
We'll demonstrate the use of mode-specific bitmaps in graphics modes with
the familiar two-color triangle whose pixel representation appears below.
. . . . * . . . .
. . . * x * . . .
. . * x x x * . .
. * x x x x x * .
* * * * * * * * *
As before, our triangle is nine pixels wide at its base and five pixels
high. The pixels indicated by an asterisk (*) are the triangle's perimeter,
while those indicated by an x represent its interior points. We need to
distinguish between these pixels because they will be different colors. The
pixels shown as periods (.) are not part of the triangle itself. They are
required to make the image rectangular, so from Fastgraph's perspective they
are indeed part of the image.
Regular Images
The Fastgraph routine fg_drwimage displays regular mode-specific
bitmapped images (by regular, we mean an image that is neither clipped nor
rotated). Its arguments and the bitmap array's subscript order are the same as
for fg_drawmap. The major difference is the bitmap structure -- we combine the
information for all colors into a single bitmap, in a way consistent with the
structure of video memory for the various modes. As with the other image
display routines, fg_drwimage displays the image on the active video page or
virtual buffer with its lower left corner at the graphics cursor position (or
the text cursor position for text modes). We'll now examine the use of
fg_drwimage in several video modes.
CGA four-color graphics modes
In the four-color CGA graphics modes (modes 4 and 5), each pixel can
assume a value between 0 and 3. This means it takes two bits to represent a
pixel, or put another way, each byte of video memory holds four pixels. Our
triangle image is nine pixels wide, so three bytes are needed for each row of
the image. Because the image is five pixels high, we need a bitmap array of at
least 15 bytes (five rows times three bytes per row) to hold the image.
The image's binary representation and its hexadecimal equivalent for the
four-color CGA graphics modes are shown here. The binary values in boldface
represent the actual image; the others are the filler bits needed to complete
each row of the bitmap after the ninth pixel. We have coded the perimeter
218 Fastgraph User's Guide
pixels to be color 1 (01 binary) and the interior pixels to be color 2 (10
binary). Any pixel whose value is zero (00 binary) is transparent and will
thus leave the contents of video memory at that position unchanged.
00 00 00 00 01 00 00 00 00 00 00 00 00 40 00
00 00 00 01 10 01 00 00 00 00 00 00 01 90 00
00 00 01 10 10 10 01 00 00 00 00 00 06 A4 00
00 01 10 10 10 10 10 01 00 00 00 00 1A A9 00
01 01 01 01 01 01 01 01 01 00 00 00 55 55 40
Example 10-3 uses this mode-specific bitmap to display the triangle in
the standard CGA four-color graphics mode (mode 4). After establishing the
video mode, the program uses fg_rect to fill the entire screen with a white
rectangle. Next, the program establishes (156,101) as the graphics cursor
position; this causes the triangle to be centered on the screen. The call to
fg_drwimage produces a triangle with a cyan perimeter (color 1) and a magenta
interior (color 2).
Example 10-3.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char triangle[] = {
0x55,0x55,0x40, 0x1A,0xA9,0x00, 0x06,0xA4,0x00,
0x01,0x90,0x00, 0x00,0x40,0x00
};
void main()
{
int old_mode;
fg_initpm();
if (fg_testmode(4,1) == 0) {
printf("This program requires a 320 ");
printf("x 200 CGA graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(4);
fg_setcolor(7);
fg_rect(0,319,0,199);
fg_move(156,101);
fg_drwimage(triangle,3,5);
fg_waitkey();
Chapter 10: Bitmapped Images 219
fg_setmode(old_mode);
fg_reset();
}
CGA two-color graphics mode
In the two-color CGA graphics mode (mode 6), each pixel can assume the
values 0 or 1. This means it takes just one bit to represent a pixel, so each
byte of video memory holds eight pixels. Our triangle image is nine pixels
wide, so two bytes are needed for each row of the image. Because the image is
five pixels high, we need a bitmap array of at least 10 bytes (five rows times
two bytes per row) to hold the image.
The image's binary representation and its hexadecimal equivalent for the
two-color CGA graphics mode are shown here. The binary values in boldface
represent the actual image; the others are the filler bits needed to complete
each row of the bitmap after the ninth pixel. We have coded both the perimeter
pixels and the interior pixels to be color 1. Any pixel whose value is zero is
transparent and will thus leave the contents of video memory at that position
unchanged.
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 08 00
0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 1C 00
0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 3E 00
0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 7F 00
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 FF 80
Example 10-4 uses this mode-specific bitmap to display the triangle in
the CGA two-color graphics mode (mode 6). After establishing the video mode,
the program establishes (316,101) as the graphics cursor position; this causes
the triangle to be centered on the screen. The call to fg_drwimage produces a
solid triangle.
Example 10-4.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char triangle[] = {
0xFF,0x80, 0x7F,0x00, 0x3E,0x00,
0x1C,0x00, 0x08,0x00
};
void main()
{
int old_mode;
220 Fastgraph User's Guide
fg_initpm();
if (fg_testmode(6,1) == 0) {
printf("This program requires a ");
printf("CGA graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(6);
fg_move(316,101);
fg_drwimage(triangle,2,5);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Tandy/PCjr 16-color graphics mode
The structure of mode-specific bitmaps for the Tandy/PCjr 16-color
graphics mode (mode 9) is the same as the mode-specific bitmap structure for
the EGA/VGA/SVGA 16-color graphics modes discussed later in this section.
Hercules graphics modes
The structure of mode-specific bitmaps for the Hercules graphics modes
(modes 11 and 12) is the same as two of the CGA graphics modes. For the
standard Hercules graphics mode (mode 11), please refer to the discussion of
CGA two-color (mode 6) bitmaps. For the low-resolution Hercules graphics mode
(mode 12), please refer to the discussion of the CGA four-color (mode 4)
bitmaps.
EGA/VGA/SVGA 16-color graphics modes
In the native EGA and VGA graphics modes (modes 13 through 18) and the
16-color SVGA graphics modes (modes 28 and 29), each pixel can assume a value
between 0 and 15. This means it takes four bits to represent a pixel, so each
byte of the bitmap holds two pixels. Our triangle image is nine pixels wide,
so five bytes are needed for each row of the image. Because the image is five
pixels high, we need a bitmap array of at least 25 bytes (five rows times five
bytes per row) to hold the image.
In these modes, it is easy to develop the hexadecimal representation of a
bitmap without first producing its binary equivalent. This is because a pixel
value and a hexadecimal digit each occupy four bits. The triangle's
hexadecimal representation for these video modes is shown here. The pixels in
boldface represent the actual image; the others are the filler values needed
to complete each row of the bitmap after the ninth pixel. We have chosen to
display the perimeter pixels in color 1 and the interior pixels in color 2.
Any pixel whose value is zero is transparent and will thus leave the contents
of video memory at that position unchanged.
Chapter 10: Bitmapped Images 221
00 00 10 00 00
00 01 21 00 00
00 12 22 10 00
01 22 22 21 00
11 11 11 11 10
Example 10-5 is similar to example 10-3, but it uses the 320x200 EGA
graphics mode (mode 13) and the mode-specific bitmap just constructed to
display the triangle. The call to fg_drwimage produces a triangle with a blue
perimeter (color 1) and a green interior (color 2).
Example 10-5.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char triangle[] = {
0x11,0x11,0x11,0x11,0x10,
0x01,0x22,0x22,0x21,0x00,
0x00,0x12,0x22,0x10,0x00,
0x00,0x01,0x21,0x00,0x00,
0x00,0x00,0x10,0x00,0x00
};
void main()
{
int old_mode;
fg_initpm();
if (fg_testmode(13,1) == 0) {
printf("This program requires a 320 ");
printf("x 200 EGA graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(13);
fg_setcolor(7);
fg_rect(0,319,0,199);
fg_move(156,101);
fg_drwimage(triangle,5,5);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
222 Fastgraph User's Guide
256-color graphics modes
In 256-color graphics modes (modes 19 through 27), each pixel can assume
a value between 0 and 255 (FF hex). This means it takes eight bits to
represent a pixel, or each byte of video memory holds one pixel. Our triangle
image is nine pixels wide, so nine bytes are needed for each row of the image.
Because the image is five pixels high, we need a bitmap array of at least 45
bytes (five rows times nine bytes per row) to hold the image. Note we will
never need any filler bits in the 256-color video modes.
It is especially simple to develop the bitmap for an image in the 256-
color modes because each byte holds exactly one pixel. The triangle's
hexadecimal representation for the 256-color graphics modes is shown here. As
before, we have coded the perimeter pixels to be color 1 (01 hex) and the
interior pixels to be color 2 (02 hex). Any pixel whose value is zero is
transparent and will thus leave the contents of video memory at that position
unchanged.
00 00 00 00 01 00 00 00 00
00 00 00 01 02 01 00 00 00
00 00 01 02 02 02 01 00 00
00 01 02 02 02 02 02 01 00
01 01 01 01 01 01 01 01 01
Example 10-6 is also similar to example 10-3, but it uses the MCGA 256-
color graphics mode (mode 19) and the mode-specific bitmap just constructed to
display the triangle. The call to fg_drwimage produces a triangle with a blue
perimeter (color 1) and a green interior (color 2).
Example 10-6.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char triangle[] = {
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x00,0x01,0x02,0x02,0x02,0x02,0x02,0x01,0x00,
0x00,0x00,0x01,0x02,0x02,0x02,0x01,0x00,0x00,
0x00,0x00,0x00,0x01,0x02,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00
};
void main()
{
int old_mode;
fg_initpm();
Chapter 10: Bitmapped Images 223
if (fg_testmode(19,1) == 0) {
printf("This program requires a 320 ");
printf("x 200 MCGA graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(19);
fg_setcolor(7);
fg_rect(0,319,0,199);
fg_move(156,101);
fg_drwimage(triangle,9,5);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Sometimes you may need to include black pixels that are not transparent
in a mode-specific bitmapped image. The easiest way to do this is to use
fg_putimage, which we'll describe shortly. Another possibility is using
fg_palette or fg_setrgb to make an unused color index black and then use that
color index for non-transparent black pixels. For example, calling
fg_palette(8,0) in a 16-color graphics mode would display color 8 pixels as
black. Similarly, fg_setrgb(248,0,0,0) in a 256-color graphics mode would
display color 248 pixels as black. The choice of colors 8 and 248 in these
examples is arbitrary; any unused color will do. Yet another possibility is to
use the masking maps discussed later in this chapter.
Virtual Buffers
The structure of mode-specific bitmaps for virtual buffers is the
same as the mode-specific bitmap structure for 256-color graphics modes
discussed in the previous section.
Text Modes
You also can use the fg_drwimage routine to display images in text video
modes (modes 0, 1, 2, 3, and 7). As one might expect, the image structure in
the text modes is rather different from the graphics modes. In Chapter 5 we
saw that each character cell on the screen actually consists of a character
and an attribute. The character value determines what character is displayed,
while the attribute value controls the character's appearance. The structure
of the attribute is:
bits attribute
0-3 foreground color
4-6 background color
7 blinking
The text mode image structure used with fg_drwimage also consists of a
series of characters and attributes. For example, the following diagram
224 Fastgraph User's Guide
illustrates the structure of an image that is three characters wide and two
characters high.
char attr char attr char attr
char attr char attr char attr
To illustrate the use of fg_drwimage in a text video mode, we'll display
the phrase "hello there" on two different lines in the center of the screen.
Furthermore, let's assume we would like the first character of each word to
appear in foreground color 1, the second in color 2, and so forth. Our image
will consist of two lines each containing five characters, and each character
requires two bytes of storage (one for the character and another for its
attribute), so we'll need a 20-byte array for holding the image. The array
really doesn't hold a bitmap as in the graphics modes, so in the text modes
the first argument passed to fg_drwimage is instead called the image array. In
our example, the structure of the image array is:
'h' 1 'e' 2 'l' 3 'l' 4 'o' 5
't' 1 'h' 2 'e' 3 'r' 4 'e' 5
The subscript order that fg_drwimage uses for text modes is the same as for
the graphics modes. For our five-row by two-column image, this means the array
subscripts would be numbered as follows:
[10] [11] [12] [13] [14] [15] [16] [17] [18] [19]
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
Depending on the character and attribute values in the image array,
fg_drwimage can display new characters and attributes, new characters leaving
the existing attribute unchanged, new attributes leaving the existing
character unchanged, or leave both the existing character and attribute
unchanged in video memory. To keep an existing character or attribute, simply
specify a value of 0 in the corresponding element of the image array. This
capability is analogous to the fact that zero-valued pixels in graphics mode
bitmaps leave video memory unchanged.
Example 10-7 demonstrates the use of fg_drwimage in the 80-column color
text mode (mode 3). After establishing the video mode and making the cursor
invisible, the program calls fg_drwimage to display the "hello there" image
just discussed (note we pass the dimensions of the image array as the number
of bytes, not the number of characters). The program waits for a keystroke and
then calls fg_drwimage again, passing a different image array (called "image")
of the same size. This array changes the first letter of both words from lower
case to upper case (leaving the attribute unchanged), and it makes the
remaining characters have the same attribute as the first character. This is
done in part by using zero-valued characters and attributes to leave video
memory unchanged. After waiting for another keystroke, the program exits.
Chapter 10: Bitmapped Images 225
Example 10-7.
#include <fastgraf.h>
void main(void);
char hello[] = {
't',1, 'h',2, 'e',3, 'r',4, 'e',5,
'h',1, 'e',2, 'l',3, 'l',4, 'o',5
};
char image[] = {
'T',0, 0,1, 0,1, 0,1, 0,1,
'H',0, 0,1, 0,1, 0,1, 0,1
};
void main()
{
int old_mode;
fg_initpm();
old_mode = fg_getmode();
fg_setmode(3);
fg_cursor(0);
fg_locate(12,37);
fg_drwimage(hello,10,2);
fg_waitkey();
fg_drwimage(image,10,2);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Clipped Images
The fg_drwimage routine does not perform clipping when displaying an
image. If you want the image to be constrained by the clipping limits (as
established by the most recent call to fg_setclip), use fg_clpimage instead of
fg_drwimage. The fg_clpimage routine takes the same three arguments as
fg_drwimage and also displays the image such that its lower left corner is at
the graphics cursor position. Unlike fg_drwimage, the fg_clpimage routine has
no effect when used in a text video mode. Because of the additional overhead
involved in checking the clipping limits, fg_clpimage is not as fast as
fg_drwimage.
Reversed Images
The fg_revimage routine displays an image reversed (that is, mirrored
about the y-axis) without clipping. It takes the same three arguments as
fg_drwimage and also displays the image such that its lower left corner is at
226 Fastgraph User's Guide
the graphics cursor position. The fg_revimage routine has no effect when used
in a text video mode.
Reversed Clipped Images
The fg_flpimage routine combines the effects of the fg_revimage and
fg_clpimage routines -- it displays a reversed image constrained by the
current clipping limits. It takes the same three arguments as fg_drwimage and
also displays the image such that its lower left corner is at the graphics
cursor position. Like the fg_clpimage routine, fg_flpimage has no effect when
used in a text video mode.
Images Without Transparent Pixels
The fg_putimage routine is the same as fg_drwimage except it does not
consider color 0 pixels to be transparent. Because it does not need to check
for transparent pixels, fg_putimage is faster than fg_drwimage. Using
fg_putimage is recommended for cases where transparency is not an issue.
Some Examples
Example 10-8 illustrates the use of fg_drwimage, fg_clpimage,
fg_revimage, fg_flpimage, and fg_putimage in the standard CGA four-color
graphics mode (mode 4). The program uses each of these routines to display a
small white arrow, as shown in this pixel map:
. . . . . . * . . .
. . . . . . * * . .
* * * * * * * * * .
* * * * * * * * * *
* * * * * * * * * .
. . . . . . * * . .
. . . . . . * . . .
As before, we must first convert this image to a bitmap. The image is ten
pixels wide and seven high. In mode 4, each pixel occupies two bits, so we
need a 21-byte array (7 rows by 3 columns) to store the image. Since we want
to make the arrow white, each pixel will be displayed in color 3 (11 binary).
Here is the bitmap and its hexadecimal equivalent for the arrow image in mode
4 (the actual image is in boldface).
00 00 00 00 00 00 11 00 00 00 00 00 00 0C 00
00 00 00 00 00 00 11 11 00 00 00 00 00 0F 00
11 11 11 11 11 11 11 11 11 00 00 00 FF FF C0
11 11 11 11 11 11 11 11 11 11 00 00 FF FF F0
11 11 11 11 11 11 11 11 11 00 00 00 FF FF C0
00 00 00 00 00 00 11 11 00 00 00 00 00 0F 00
Chapter 10: Bitmapped Images 227
00 00 00 00 00 00 11 00 00 00 00 00 00 0C 00
After establishing the video mode, the program fills the screen with
color 1 pixels and defines a clipping region. It then uses fg_drwimage to
display the arrow pointing to the right and fg_clpimage to do the same thing,
but with respect to the clipping limits. Because the left edge of the arrow is
displayed at x=10 and the right clipping limit is at x=15, the call to
fg_clpimage only draws the first six columns of the arrow (that is, it does
not draw the arrow head).
Next, example 10-8 uses fg_revimage to display the arrow pointing to the
left. To allow for the filler pixels, we must establish the graphics cursor
position two pixels to the left of the position used by fg_drwimage if we want
the tip of the left-pointing arrow to align with the tail of the right-
pointing arrow. The program then uses fg_flpimage to display an arrow pointing
to the left with regard to the clipping limits. The call to fg_flpimage
displays the arrow head and the first two columns of the arrow shaft. Finally,
the program uses fg_putimage to display the unclipped right-pointing arrow
without transparent pixels (this produces a black border around the arrow).
Example 10-8.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char arrow[] = {
0x00,0x0C,0x00, 0x00,0x0F,0x00, 0xFF,0xFF,0xC0,
0xFF,0xFF,0xF0, 0xFF,0xFF,0xC0, 0x00,0x0F,0x00,
0x00,0x0C,0x00
};
void main()
{
int old_mode;
fg_initpm();
if (fg_testmode(4,1) == 0) {
printf("This program requires a 320 ");
printf("x 200 CGA graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(4);
fg_setcolor(1);
fg_fillpage();
fg_setclip(0,15,0,199);
fg_move(10,10);
fg_drwimage(arrow,3,7);
fg_move(10,20);
fg_clpimage(arrow,3,7);
228 Fastgraph User's Guide
fg_move(8,30);
fg_revimage(arrow,3,7);
fg_move(8,40);
fg_flpimage(arrow,3,7);
fg_move(8,50);
fg_putimage(arrow,3,7);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Example 10-9 is the same as example 10-8, but it uses the low resolution
EGA graphics mode (mode 13). If we changed the mode number specified in the
calls to fg_testmode and fg_setmode, the program also would run in any 16-
color graphics mode. In these modes, we store two pixels per byte in the
bitmap array, so we need a 35-byte array (7 rows by 5 columns) to store the
image. Here is the bitmap's hexadecimal equivalent for the arrow image in mode
13, followed by the program to display it.
00 00 00 F0 00
00 00 00 FF 00
FF FF FF FF F0
FF FF FF FF FF
FF FF FF FF F0
00 00 00 FF 00
00 00 00 F0 00
Example 10-9.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char arrow[] = {
0x00,0x00,0x00,0xF0,0x00,
0x00,0x00,0x00,0xFF,0x00,
0xFF,0xFF,0xFF,0xFF,0xF0,
0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xF0,
0x00,0x00,0x00,0xFF,0x00,
0x00,0x00,0x00,0xF0,0x00
};
void main()
{
Chapter 10: Bitmapped Images 229
int old_mode;
fg_initpm();
if (fg_testmode(13,1) == 0) {
printf("This program requires a 320 ");
printf("x 200 EGA graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(13);
fg_setcolor(1);
fg_fillpage();
fg_setclip(0,15,0,199);
fg_move(10,10);
fg_drwimage(arrow,5,7);
fg_move(10,20);
fg_clpimage(arrow,5,7);
fg_move(8,30);
fg_revimage(arrow,5,7);
fg_move(8,40);
fg_flpimage(arrow,5,7);
fg_move(8,50);
fg_putimage(arrow,5,7);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Retrieving Images
Sometimes it's necessary to retrieve an image from video memory and store
it in one or more arrays as a bitmapped image. Fastgraph includes two
routines, fg_getmap and fg_getimage, for this purpose. The fg_getmap routine
retrieves pixels of the current color index and stores them in the mode-
independent bitmap format used by fg_drawmap. The fg_getimage routine
retrieves an image and stores it in the mode-specific bitmap format used by
fg_drwimage, fg_clpimage, fg_revimage, fg_flpimage, and fg_putimage. The
arguments to fg_getmap and fg_getimage are respectively analogous to those of
fg_drawmap and fg_drwimage: the first is an array (passed by reference) to
receive the bitmap, the second is the width of the bitmap in bytes, and the
last is the height of the bitmap in pixel rows. With either routine, the
graphics cursor position on the active video page defines the lower left
corner of the image to retrieve.
If we want to use fg_getmap to retrieve an image containing more than one
color, we must call the routine once per color. In this case we'll usually
want to pass different bitmap arrays to fg_getmap (or perhaps different
offsets into the same array). This might seem unusual at first, but it
parallels the behavior of the fg_drawmap routine. That is, to display a
multicolor image using fg_drawmap, we must call it once for each color in the
image.
230 Fastgraph User's Guide
Example 10-10 demonstrates a typical use of the fg_getmap routine. The
program displays the word "text" in the upper left corner of the screen using
a 320x200 graphics mode. It uses fg_getmap to retrieve the word as an image
and then displays it in a new position with the fg_drawmap routine. Let's look
at the program now, and afterward we'll more closely examine the screen
coordinates and the structure of the bitmap array.
Example 10-10.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
void main()
{
char bitmap[32];
int old_mode, new_mode;
fg_initpm();
new_mode = fg_bestmode(320,200,1);
if (new_mode < 0 || new_mode == 12) {
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
fg_setcolor(9);
fg_text("text",4);
fg_waitkey();
fg_move(0,7);
fg_getmap(bitmap,4,8);
fg_move(4,15);
fg_drawmap(bitmap,4,8);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
In all 320x200 graphics video modes, individual characters are 8 pixels
wide and 8 pixels high. This means the lower left corner of the (0,0)
character cell is referenced by the screen coordinates (0,7). Hence, these are
the coordinates of the first call to fg_move. The image retrieved in example
10-10 is four characters long (32 pixels wide), so we need a bitmap array
capable of holding 8 rows of 32 pixels (4 bytes) each. Our bitmap array is
therefore a 32-byte array, logically structured to have 4 columns and 8 rows.
These values are the width and height arguments passed to fg_getmap and
fg_drawmap.
Chapter 10: Bitmapped Images 231
After it retrieves the image, example 10-10 displays it one line below
and one-half character cell (four pixels) to the right of its original
position. In other words, the program displays the image four pixels to the
right of the (1,0) character cell. The lower left corner of that cell is
referenced by the screen coordinates (0,15), so the image should appear at the
position (4,15). These are the coordinates of the second call to fg_move.
Example 10-11 illustrates the use of fg_getmap and fg_drawmap to retrieve
and display a two-color image. This example is similar to example 10-10, but
this program first draws a rectangle in the upper left corner of the screen
and then displays the word "text" on top of the rectangle in a different
color. Each character in a 320x200 graphics video mode is 8 pixels wide and 8
pixels high, so the rectangle must be 32 pixels wide (4 characters times 8
pixels per character) and 8 pixels high. The image to retrieve will be the
same size as the rectangle.
The image retrieved in example 10-10 required a 32-byte array, logically
structured to have 4 columns and 8 rows. Example 10-11 will retrieve an image
of the same structure, but the image contains two colors instead of just one.
This means we need two 32-byte arrays, one for each color, to hold the image.
We could instead use a single 64-byte array and pass an offset into that array
(specifically, &bitmap[32]) for processing the second color.
Example 10-11.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
void main()
{
char bitmap1[32], bitmap2[32];
int old_mode, new_mode;
fg_initpm();
new_mode = fg_bestmode(320,200,1);
if (new_mode < 0 || new_mode == 12) {
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
fg_setcolor(7);
fg_rect(0,31,0,7);
fg_setcolor(9);
fg_text("text",4);
fg_waitkey();
fg_move(0,7);
fg_setcolor(7);
fg_getmap(bitmap1,4,8);
fg_setcolor(9);
232 Fastgraph User's Guide
fg_getmap(bitmap2,4,8);
fg_move(4,15);
fg_setcolor(7);
fg_drawmap(bitmap1,4,8);
fg_setcolor(9);
fg_drawmap(bitmap2,4,8);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Example 10-12 is similar to example 10-11, but it uses fg_getimage and
fg_drwimage instead of fg_getmap and fg_drawmap to retrieve and display the
image. That is, it uses the mode-specific rather than the mode-independent
image retrieval and display routines. When using the mode-specific routines,
the size of the bitmap needed to hold the image depends on the video mode. For
programs that run in only one video mode, bitmap widths are constant, but when
a program must run in several video modes, the width is variable. The
Fastgraph routine fg_imagesiz computes the number of bytes required to store a
mode-specific bitmapped image of specified dimensions. Its two integer
arguments specify the image width and height in pixels.
The program computes the image width in bytes by passing a height of 1 to
fg_imagesiz. The size of the bitmap array in example 10-12 is 256 bytes, the
size required in 256-color graphics modes (32 bytes times 8 bytes). Other
video modes require less storage, so in these modes only a portion of the
bitmap array will actually be used. The image width is then used in the calls
to both fg_getimage and fg_drwimage.
Example 10-12.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
void main()
{
char bitmap[256];
int old_mode, new_mode;
int width;
fg_initpm();
new_mode = fg_bestmode(320,200,1);
if (new_mode < 0 || new_mode == 12) {
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
width = (int)fg_imagesiz(32,1);
Chapter 10: Bitmapped Images 233
fg_setcolor(7);
fg_rect(0,31,0,7);
fg_setcolor(9);
fg_text("text",4);
fg_waitkey();
fg_move(0,7);
fg_getimage(bitmap,width,8);
fg_move(4,15);
fg_drwimage(bitmap,width,8);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
While this example used an array to store the image, it's usually preferable
to allocate dynamic memory for this purpose. We could have done this in
example 10-12 by calling fg_imagesiz with arguments of 32 (width) and 8
(height). The routine's return value would then tell us the number of bytes we
would need to allocate.
We can also use fg_getimage to retrieve images in text video modes. In
text modes, however, there are a few differences we must consider when using
fg_getimage. First, the text cursor position, not the graphics cursor
position, specifies the lower left corner of the image. Hence, we must use
fg_locate instead of fg_move to define the image location. Second, the image
width is always twice the number of characters per image row (that is, for
each character we have a character byte and an attribute byte). The fg_getmap
routine has no effect when used in a text video mode.
Example 10-13 shows a simple use of fg_getimage in text modes. This
program is similar to example 10-12, but it runs in an 80-column text mode
rather than a 320x200 graphics mode. As before, the program will retrieve the
four characters "text" as an image from the upper left corner of the screen
and then display it in a different location. Because the image consists of
four characters in one row, the image width is 8 bytes and the image height is
1.
Example 10-13.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
void main()
{
int old_mode;
char image[8];
fg_initpm();
old_mode = fg_getmode();
234 Fastgraph User's Guide
if (fg_testmode(3,1))
fg_setmode(3);
else if (fg_testmode(7,1))
fg_setmode(7);
else {
printf("This program requires\n");
printf("an 80-column display.\n");
exit(1);
}
fg_cursor(0);
fg_setattr(9,7,0);
fg_text("text",4);
fg_waitkey();
fg_locate(0,0);
fg_getimage(image,8,1);
fg_locate(1,1);
fg_drwimage(image,8,1);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Finally, here's a tip that's worth remembering. In the native EGA and VGA
graphics modes (13 to 18) and the 16-color SVGA graphics modes (28 and 29),
the routines for displaying and retrieving mode-specific bitmaps can be
anywhere from 10% to 20% faster if the current graphics x position is an even
number. This is because these routines must perform additional bitmap
alignment when displaying or retrieving images starting at odd-numbered
pixels.
Inverting Bitmaps
Fastgraph's mode-independent and mode-specific bitmapped image display
routines expect images to be stored starting with the bottom row and
proceeding toward the top. This convention is often contrary to the "top to
bottom" row order used in other graphics libraries. The fg_invert routine
reverses the row order of bitmapped images, so a "top to bottom" image becomes
a "bottom to top" image, or vice versa. This will often make it easier to
import such images from other sources for use with Fastgraph's bitmapped image
display routines. Note that fg_invert does not change the orientation for
Fastgraph's bitmapped image display routines; it merely reverses the row order
of the image itself.
The fg_invert routine requires three arguments. The first is the address
of the array containing the mode-independent or mode-specific bitmapped image
data. The resulting inverted image is stored in this same array. The second
and third arguments respectively specify the bitmap width and height in bytes.
Example 10-14 is a modified version of example 10-6 that defines the
triangle's bitmap data starting with the top row and proceeding toward the
bottom. To display this image with Fastgraph's fg_drwimage routine, we must
Chapter 10: Bitmapped Images 235
translate the bitmapped image to the "bottom to top" format. The program
performs this translation with fg_invert immediately after setting the video
mode (though it could be done anytime before calling fg_drwimage). Other than
the additional fg_invert call and the order of the bitmap data, example 10-14
is the same as example 10-6.
Example 10-14.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char triangle[] = {
0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x02,0x01,0x00,0x00,0x00,
0x00,0x00,0x01,0x02,0x02,0x02,0x01,0x00,0x00,
0x00,0x01,0x02,0x02,0x02,0x02,0x02,0x01,0x00,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
};
void main()
{
int old_mode;
fg_initpm();
if (fg_testmode(19,1) == 0) {
printf("This program requires a 320 ");
printf("x 200 MCGA graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(19);
fg_invert(triangle,9,5);
fg_setcolor(7);
fg_rect(0,319,0,199);
fg_move(156,101);
fg_drwimage(triangle,9,5);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Note that fg_invert also can be used to create inverted versions of any
mode-independent or mode-specific bitmapped image. This means you can create
versions of bitmaps mirrored about the x-axis, somewhat analogous to the way
fg_revimage displays images mirrored about the y-axis.
236 Fastgraph User's Guide
Converting Mode-Specific Bitmaps
Earlier in this chapter we presented a bitmapped image format that was
independent of the video mode (such images are displayed with fg_drawmap or
fg_clipmap). While this format works well for images with one or two colors,
the performance can degrade significantly if the image contains many colors.
In this section we'll show how Fastgraph's "one pixel per byte" mode-specific
bitmap format used with 256-color graphics modes and virtual buffers can
provide an alternate way to use the same image data in multiple video modes.
The basis of this scheme is to store all bitmaps in the "one pixel per
byte" format. When using 256-color graphics modes or virtual buffers, we
simply use the "one pixel per byte" bitmaps with the fg_drwimage family of
routines because the bitmaps are already in the expected format. However, when
using graphics modes with fewer colors, we must translate the bitmaps to a
suitable format for those modes. Fastgraph's fg_pack routine provides an easy
way to do this: it converts bitmapped images in the "one pixel per byte"
format to the mode-specific bitmap format for the current video mode. The
converted bitmaps can then be displayed with the fg_drwimage family.
The fg_pack routine's first two arguments are the addresses of the source
and destination bitmap arrays. The source array contains the "one pixel per
byte" bitmapped image, and the destination array will receive the converted
mode-specific image (it's important to make sure the destination array is
large enough to hold the converted image). The last two fg_pack arguments
specify the width and height in pixels of the source bitmap. In 256-color
graphics modes, or when a virtual buffer is active, fg_pack merely copies the
source array contents to the destination array.
Example 10-15 shows how you can use the same bitmap data in 256-color and
16-color graphics modes. We define our familiar triangle bitmap in the 256-
color mode-specific format, as in example 10-6. The program first displays the
triangle bitmap in the standard VGA/MCGA 320x200 256-color graphics mode (mode
19) against a gray background. After a keystroke, the program switches to the
EGA/VGA 320x200 16-color graphics mode (mode 13). In this mode, fg_drwimage
expects two pixels per bitmap byte, so we must call fg_pack to convert the
bitmap data to this format. We store the resulting bitmap in the triangle16
array and again use fg_drwimage to display the triangle bitmap.
Example 10-15.
#include <fastgraf.h>
void main(void);
char triangle[] = {
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x00,0x01,0x02,0x02,0x02,0x02,0x02,0x01,0x00,
0x00,0x00,0x01,0x02,0x02,0x02,0x01,0x00,0x00,
0x00,0x00,0x00,0x01,0x02,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00
};
char triangle16[25];
void main()
{
Chapter 10: Bitmapped Images 237
int old_mode;
fg_initpm();
old_mode = fg_getmode();
fg_setmode(19);
fg_setcolor(7);
fg_fillpage();
fg_move(156,101);
fg_drwimage(triangle,9,5);
fg_waitkey();
fg_setmode(13);
fg_setcolor(7);
fg_fillpage();
fg_pack(triangle,triangle16,9,5);
fg_move(156,101);
fg_drwimage(triangle16,5,5);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Note that the 256-color bitmap is nine bytes wide and five bytes tall. When we
convert the image to the 16-color mode-specific format, the bitmap width is
reduced to five bytes because two pixels are packed into each byte. The second
pixel in the last byte of each row becomes a transparent filler pixel (that
is, its value is zero).
As you might guess, Fastgraph's fg_unpack routine performs the opposite
function of fg_pack. That is, it converts a bitmap from the mode-specific
format of the current video mode to the "one pixel per byte" format. The
fg_unpack routine is intended as a helper function for displaying mode-
specific images in virtual buffers when using video modes with fewer than 256
colors. When a virtual buffer is active, fg_drwimage always expects the bitmap
to be in the "one pixel per byte" format, regardless of the current video
mode. The fg_unpack routine makes it easy to convert images to this format
before displaying them in a virtual buffer.
The fg_unpack routine's first two arguments are the addresses of the
source and destination bitmap arrays. The source array contains the mode-
specific bitmapped image, and the destination array will receive the converted
"one pixel per byte" image. The last fg_unpack argument specifies the size of
the source array in bytes. Like fg_pack, fg_unpack merely copies the source
array contents to the destination array in 256-color graphics modes or when a
virtual buffer is active.
Example 10-16 illustrates how to use fg_unpack to convert mode-specific
bitmaps to the virtual buffer format. The program uses the 10-pixel by 7-pixel
arrow bitmap of example 10-9 and runs in the EGA/VGA 320x200 16-color graphics
mode (mode 13). In this mode, two pixels are packed into each bitmap byte, so
the size of the bitmap array is 5x7, or 35 bytes. The call to fg_unpack
converts the mode-specific image in the 35-byte arrow array into a "one pixel
per byte" format image, storing the result in the 70-byte arrow256 array.
238 Fastgraph User's Guide
We'll create a 70-byte virtual buffer -- just large enough to hold the 10x7
arrow bitmap -- and display the arrow256 bitmap in it against a light blue
(color 9) background. Finally, we'll use fg_vbpaste to display the virtual
buffer contents in the middle of the screen.
Example 10-16.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char arrow[] = {
0x00,0x00,0x00,0xF0,0x00,
0x00,0x00,0x00,0xFF,0x00,
0xFF,0xFF,0xFF,0xFF,0xF0,
0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xF0,
0x00,0x00,0x00,0xFF,0x00,
0x00,0x00,0x00,0xF0,0x00
};
char arrow256[70];
#ifdef FG32
char buffer[70];
#else
char far buffer[70];
#endif
void main()
{
int handle;
int old_mode;
fg_initpm();
if (fg_testmode(13,1) == 0) {
printf("This program requires a 320 ");
printf("x 200 EGA graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(13);
fg_unpack(arrow,arrow256,35);
fg_vbinit();
handle = fg_vbdefine(buffer,10,7);
fg_vbopen(handle);
fg_setcolor(9);
fg_fillpage();
fg_move(0,6);
fg_drwimage(arrow256,10,7);
fg_vbpaste(0,9,0,6,156,101);
fg_waitkey();
Chapter 10: Bitmapped Images 239
fg_vbclose();
fg_setmode(old_mode);
fg_reset();
}
Bitmap Scaling and Shearing
Fastgraph's fg_scale routine performs horizontal and vertical scaling of
bitmapped images. It expects a source bitmap stored in the "one pixel per
byte" format of Fastgraph's 256-color modes, and it returns an expanded or
reduced bitmap in the same format. To scale images in graphics modes with
fewer than 256 colors, you must first use fg_unpack to convert the bitmap to
the format expected by fg_scale, perform the scaling, and finally use fg_pack
to convert the scaled image back to the mode-specific format. Because
Fastgraph's virtual buffers also use the one pixel per byte format, you can
also use fg_scale to scale images stored in virtual buffers.
The fg_scale routine has six arguments. The first two specify the
addresses of the source and destination bitmap arrays. The source array
contains the original (unscaled) bitmapped image; the destination array will
receive the expanded or reduced (scaled) bitmap. Both bitmaps are stored in
the "one pixel per byte" format. The third and fourth arguments specify the
width and height in pixels of the unscaled image, while the fifth and sixth
arguments do the same for the resulting scaled image.
Example 10-17 shows how to expand and reduce bitmapped images with
fg_scale. The program displays a 64x40 light blue rectangle with a white
border and the word SCALE centered inside it, in the upper left corner of the
screen. It retrieves the rectangle contents as a mode-specific bitmap using
fg_getimage. The first fg_scale call increases the size of this bitmap by 10
pixels in both directions, meaning the 64x40 image becomes a 74x50 image. The
program then displays the expanded bitmap in the lower left corner of the
screen using fg_putimage. The second fg_scale call reduces the original bitmap
by a factor of two to create a 32x20 bitmap. The reduced bitmap is then
displayed in the lower right corner, again using fg_putimage. Note that
example 10-17 runs in mode 19, which is a 256-color graphics mode, so
fg_getimage automatically stores the original bitmap in the "one pixel per
byte" format expected by fg_scale.
Example 10-17.
#include <fastgraf.h>
void main(void);
char source[64*40], dest[74*50];
void main()
{
/* initialize the video environment */
fg_initpm();
fg_setmode(19);
/* draw a blue rectangle with a thick white border */
240 Fastgraph User's Guide
fg_setcolor(9);
fg_rect(0,63,0,39);
fg_setcolor(15);
fg_boxdepth(5,5);
fg_box(0,63,0,39);
fg_move(32,20);
fg_justify(0,0);
fg_print("SCALE",5);
/* retrieve the rectangle as a mode-specific bitmap */
fg_move(0,39);
fg_getimage(source,64,40);
fg_waitkey();
/* expand the bitmap by 10 pixels in each direction and */
/* then display it in the lower left corner of the screen */
fg_move(0,199);
fg_scale(source,dest,64,40,74,50);
fg_putimage(dest,74,50);
fg_waitkey();
/* reduce the original bitmap by 50% in each direction and */
/* then display it in the lower right corner of the screen */
fg_move(288,199);
fg_scale(source,dest,64,40,32,20);
fg_putimage(dest,32,20);
fg_waitkey();
/* restore 80x25 text mode and exit */
fg_setmode(3);
fg_reset();
}
Shearing can be thought of as anchoring one corner of a rectangular
region and stretching the opposite corner horizontally or vertically. For
example, bitmaps containing text or other characters could be sheared
horizontally to the right for an italic effect. A sheared image will always be
larger than the original image, and it will contain empty triangular areas at
its corners. The empty areas will be filled with color 0 pixels, meaning they
will be transparent when you display a sheared image with the fg_drwimage
family of routines. Like fg_scale, fg_shear expects bitmaps in the "one pixel
per byte" format and can likewise be used with images stored in virtual
buffers.
The fg_shear routine has six arguments. The first two specify the
addresses of the source and destination bitmap arrays. The source array
contains the original bitmapped image; the destination array will receive the
sheared bitmap. Both bitmaps are stored in the "one pixel per byte" format.
The third and fourth arguments specify the width and height in pixels of the
original image. For horizontal shears, the fifth argument specifies the
Chapter 10: Bitmapped Images 241
resulting width in pixels of the sheared bitmap. For vertical shears, it
specifies the resulting height.
The final fg_shear argument defines the shear type. Four distinct shear
types are available:
* horizontal left shear (region's bottom edge is stretched to the right)
* horizontal right shear (region's top edge is stretched to the right)
* vertical left shear (region's left edge is stretched up)
* vertical right shear (region's right edge is stretched up)
The type is selected by a value between 0 and 3, respectively corresponding to
the above four shear types. For example, shear type 2 represents a vertical
left shear.
Example 10-18 displays a 64x40 light blue rectangle with a white border
and the word SHEAR centered inside it, in the upper left corner of the screen.
It retrieves the rectangle contents as a mode-specific bitmap using
fg_getimage. The program then calls fg_shear to perform a 16-pixel horizontal
right shear, which stretches the image's top edge 16 pixels to the right. This
produces an 80x40 bitmap, which is then displayed in the lower left corner of
the screen with fg_putimage. Because this example runs in mode 19, which is a
256-color graphics mode, fg_getimage automatically stores the original bitmap
in the "one pixel per byte" format expected by fg_shear.
Example 10-18.
#include <fastgraf.h>
void main(void);
char source[64*40], dest[80*40];
void main()
{
/* initialize the video environment */
fg_initpm();
fg_setmode(19);
/* draw a blue rectangle with a thick white border */
fg_setcolor(9);
fg_rect(0,63,0,39);
fg_setcolor(15);
fg_boxdepth(5,5);
fg_box(0,63,0,39);
fg_move(32,20);
fg_justify(0,0);
fg_print("SHEAR",5);
/* retrieve the rectangle as a mode-specific bitmap */
fg_move(0,39);
fg_getimage(source,64,40);
fg_waitkey();
242 Fastgraph User's Guide
/* shear the bitmap horizontally and to the right 16 pixels */
/* then display it in the lower left corner of the screen */
fg_move(0,199);
fg_shear(source,dest,64,40,80,1);
fg_putimage(dest,80,40);
fg_waitkey();
/* restore 80x25 text mode and exit */
fg_setmode(3);
fg_reset();
}
It's possible to use fg_shear for rudimentary bitmap rotation. Shearing
an image horizontally left and then vertically right by the same amount will
rotate an image counterclockwise. Similarly, shearing horizontally right and
then vertically left will rotate it clockwise.
Virtual buffers use the same "one pixel per byte" format expected by
fg_scale and fg_shear. This means you can pass virtual buffer addresses to
these functions and apply scaling and shearing operations on virtual buffers.
Note, however that 16-bit modes limit the size of arrays passed to fg_scale
and fg_shear to 64K bytes, meaning you cannot apply these functions to larger
virtual buffers. Further, the address of a real mode virtual buffer is a
segment:offset pair, so you must use the large memory model to scale or shear
images residing in virtual buffers in real mode programs.
Example 10-19 demonstrates how to scale the contents of a virtual buffer.
The program creates two virtual buffers -- one is 320x200 pixels and the other
is one-fourth this size, or 80x50 pixels. The CORAL.PCX image is loaded into
the 320x200 virtual buffer using the fg_loadpcx routine and then copied to the
visual page. The program then calls fg_scale, passing it the two virtual
buffer handles, to reduce the image to one-fourth its original size. The
resulting image is stored in the 80x50 virtual buffer and finally copied to
the lower left corner of the visual page.
Example 10-19.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
#if defined(__TURBOC__)
#include <alloc.h>
#else
#include <malloc.h>
#endif
void main(void);
void main()
{
int handle1, handle2;
#if defined(__WATCOMC__) || defined(__HIGHC__)
char *buffer1, *buffer2;
#else
Chapter 10: Bitmapped Images 243
char far *buffer1, far *buffer2;
#endif
fg_initpm();
fg_setmode(19);
fg_vbinit();
#if defined(__WATCOMC__) || defined(__HIGHC__)
buffer1 = (char *)malloc(320*200);
buffer2 = (char *)malloc(80*50);
#elif defined(__TURBOC__)
buffer1 = (char far *)farmalloc(320L*200L);
buffer2 = (char far *)farmalloc(80L*50L);
#else
buffer1 = (char far *)halloc(320L*200L,1);
buffer2 = (char far *)halloc(80L*50L,1);
#endif
if (buffer1 == NULL || buffer2 == NULL)
{
fg_setmode(3);
fg_reset();
printf("Could not create the virtual buffers.\n");
exit(1);
}
handle1 = fg_vbdefine(buffer1,320,200);
handle2 = fg_vbdefine(buffer2,80,50);
fg_vbopen(handle1);
fg_loadpcx("CORAL.PCX",0);
fg_vbpaste(0,319,0,199,0,199);
fg_waitkey();
fg_scale(buffer1,buffer2,320,200,80,50);
fg_vbopen(handle2);
fg_vbpaste(0,79,0,49,0,199);
fg_waitkey();
fg_vbclose();
fg_setmode(3);
fg_reset();
}
In example 10-19, we created the virtual buffers with fg_vbdefine, so we
knew their addresses. What if we were using BASIC or real mode Pascal and
created them with fg_vballoc? In this case the virtual buffer addresses
wouldn't be immediately available to the program. Fortunately, there is an
easy solution. Fastgraph's fg_vbaddr function returns the address of the
specified virtual buffer; its only argument is the virtual buffer handle. In
16-bit modes, the address will be a real mode segment:offset pair or protected
mode selector:offset pair. In 32-bit modes, it will be an offset into the
default data segment. If you were using fg_vballoc in example 10-19, the
virtual buffer creation and address retrieval could be done as follows:
char far *buffer1, far *buffer2;
244 Fastgraph User's Guide
handle1 = fg_vballoc(320,200);
handle2 = fg_vballoc(80,50);
if (handle1 < 0 || handle2 < 0) {
fg_setmode(3);
fg_reset();
printf("Could not create the virtual buffers.\n");
exit(1);
}
buffer1 = (char far *)fg_vbaddr(handle1);
buffer2 = (char far *)fg_vbaddr(handle2);
The statements to release the memory allocated to the virtual buffers would
be:
fg_vbclose();
fg_vbfree(handle1);
fg_vbfree(handle2);
Pixel Run Maps
The bitmaps used with the fg_drawmap, fg_drwimage, and related routines
can consume array space quite rapidly. This is especially true if the image is
large or contains many colors. For example, a mode-independent bitmapped image
that occupies the entire screen in a 320x200 graphics mode requires 8,000
bytes of space per color. Fastgraph provides another mode-independent image
format called pixel run maps, which are more efficient in terms of space.
Pixel run maps are structured just like the pixel run files introduced in the
previous chapter, but the image resides in an array instead of a file.
Let's return to our familiar triangle example and show how we could use a
pixel run map to display it.
. . . . * . . . .
. . . * x * . . .
. . * x x x * . .
. * x x x x x * .
* * * * * * * * *
As before, the pixels indicated by an asterisk (*) are the triangle's
perimeter, while those indicated by an x represent its interior points. The
pixels shown as periods (.) are not part of the triangle itself, but they are
part of the pixel run map.
Using the standard pixel run format introduced in the previous chapter,
we see it takes 16 pixel runs to store our triangle image as a pixel run map.
If we want to display the perimeter pixels in color 1, the interior pixels in
color 2, and the filler area in color 7, the pixel run map would contain 16
sets of (color,count) pairs: (1,9), (7,1), (1,1), (2,5), (1,1), (7,3), (1,1),
(2,3), (1,1), (7,5), (1,1), (2,1), (1,1), (7,7), (1,1), and (7,4). Unlike the
bitmapped image formats already discussed, pixel run maps have no provision
for transparent colors.
The Fastgraph routine fg_display displays an image stored as a pixel run
map. The fg_display routine expects three arguments. The first is an array
containing the pixel runs (passed by reference), the second is the number of
Chapter 10: Bitmapped Images 245
pixel runs in the array, and the third is the width in pixels of the image. As
with the other image display routines, fg_display displays the image such that
its lower left corner is at the graphics cursor position on the active video
page or virtual buffer. Again, the format of the pixel run map is the same as
that of a standard pixel run file. In addition, any display patterns defined
by fg_pattern also apply to fg_display.
Example 10-20 uses the fg_display routine to display the triangle as a
pixel run map in a 320x200 graphics mode. The program displays the triangle
against a background of color 7, so the selection of color 7 for the filler
area was important. If some other color were chosen, the filler area would not
blend in with the background.
Example 10-20.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char triangle[] = {
1,9, 7,1, 1,1, 2,5, 1,1, 7,3, 1,1, 2,3,
1,1, 7,5, 1,1, 2,1, 1,1, 7,7, 1,1, 7,4
};
void main()
{
int old_mode, new_mode;
fg_initpm();
new_mode = fg_bestmode(320,200,1);
if (new_mode < 0 || new_mode == 12) {
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
fg_setcolor(7);
fg_rect(0,319,0,199);
fg_move(156,101);
fg_display(triangle,16,9);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
As you might guess, Fastgraph also offers a packed pixel run map image
format analogous to the packed pixel run file format introduced in the
previous chapter. Example 10-21 is the same as example 10-20, but it uses
fg_displayp rather than fg_display to display the image. Note the use of
246 Fastgraph User's Guide
hexadecimal numbers for defining the packed color values, which of course is
not necessary but certainly easier to read than expressing the quantities as
decimal numbers. As with fg_display, any display patterns defined by
fg_pattern also apply to fg_displayp.
Example 10-21.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char triangle[] = {
0x17,9,1, 0x12,1,5, 0x17,1,3, 0x12,1,3,
0x17,1,5, 0x12,1,1, 0x17,1,7, 0x17,1,4
};
void main()
{
int old_mode, new_mode;
fg_initpm();
new_mode = fg_bestmode(320,200,1);
if (new_mode < 0 || new_mode == 12) {
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
fg_setcolor(7);
fg_rect(0,319,0,199);
fg_move(156,101);
fg_displayp(triangle,16,9);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Both fg_display and fg_displayp require the pixel run image to be stored
in an array. In examples 10-20 and 10-21, the image is defined within the
program itself. We can also use these routines in place of fg_dispfile when
the image is stored in a file if we first read the file contents into an
array. Example 10-22 demonstrates this procedure. The program displays two
identical images stored in files, one in standard pixel run format and the
other in packed pixel run format.
The first image, in standard pixel run format, is in the file CORAL.SPR.
Note the program must open the file for reading in binary mode ("rb" in the
call to fopen). The program reads the file's entire contents into the
pixel_runs array, whose size must be at least as large as the file size.
Chapter 10: Bitmapped Images 247
Because the image is stored in standard pixel run format, the number of pixel
runs is one-half the file size. The program then uses fg_move to establish the
lower left corner of the screen as the graphics cursor position and then calls
fg_display to display the image. The image fills the entire screen, so its
width is 320 pixels.
After waiting for a keystroke, the program similarly displays the second
image. This image is in the file CORAL.PPR and is stored in packed pixel run
format. Because the image is packed, the number of pixel runs is two-thirds
the file size. The program then clears the previous image from the screen and
calls fg_displayp to display the image. After another keystroke, the program
restores the original video mode and screen attributes and returns to DOS.
Example 10-22.
#include <fastgraf.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char pixel_runs[20000];
void main()
{
FILE *stream;
int file_size, run_count;
int old_mode, new_mode;
fg_initpm();
new_mode = fg_bestmode(320,200,1);
if (new_mode < 0 || new_mode == 12) {
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
stream = fopen("CORAL.SPR","rb");
file_size = (int)(filelength(fileno(stream)));
fread(pixel_runs,sizeof(char),file_size,stream);
fclose(stream);
run_count = file_size / 2;
fg_move(0,199);
fg_display(pixel_runs,run_count,320);
fg_waitkey();
stream = fopen("CORAL.PPR","rb");
file_size = (int)(filelength(fileno(stream)));
fread(pixel_runs,sizeof(char),file_size,stream);
fclose(stream);
run_count = file_size / 3 * 2;
fg_erase();
fg_displayp(pixel_runs,run_count,320);
248 Fastgraph User's Guide
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Masking Maps
It is not possible to include color 0 pixels in an image displayed with
fg_drwimage, fg_clpimage, fg_revimage, or fg_flpimage. This is because these
routines consider color 0 pixels to be transparent, which means such pixels do
not affect the corresponding pixels in video memory. There are times, however,
when you will want color 0 pixels to be destructive, or replace the video
memory contents.
Consider again the arrow image of example 10-8. In that example, we
displayed a white (color 3) arrow against a black (color 0) background in the
standard CGA four-color graphics mode. Suppose, though, that we want to do
just the opposite -- display a black (color 0) arrow against a white (color 3)
background. We could of course use fg_putimage, fg_drawmap, or one of the
routines for displaying pixel run maps, but these methods do not support
clipping or reversing an image. There are, however, four Fastgraph routines
designed just for this purpose. These routines are fg_drawmask, fg_clipmask,
fg_revmask, and fg_flipmask.
Each of these routines uses a data structure called a masking map. A
masking map is similar in structure to a pixel run map, but it does not
include any information about colors. Instead, it consists of a series of
pixel runs that alternate between protected and unprotected pixels. An example
might best clarify this.
Once again, here is the arrow image of example 10-8.
. . . . . . * . . .
. . . . . . * * . .
* * * * * * * * * .
* * * * * * * * * *
* * * * * * * * * .
. . . . . . * * . .
. . . . . . * . . .
This time, though, we want the arrow to appear in color 0. Put another way, we
need the "period" pixels (.) to protect video memory, while we want the
"asterisk" pixels (*) to zero video memory. Looking at this problem from the
perspective of a pixel run map, we have an alternating series of "protect" and
"zero" runs. We don't need any information about pixel colors, just whether to
protect or to zero video memory.
This is precisely the structure of a masking map. Starting from the lower
left corner of the image and proceeding to the right, wrapping up to the next
row when needed, we could represent this image as a masking map with 6
protected pixels, 1 zeroed pixel, 9 protected pixels, 2 zeroed pixels, and so
on. In general, the structure of a masking map is as follows.
Chapter 10: Bitmapped Images 249
[1] length of 1st protect run
[2] length of 1st zero run
[3] length of 2nd protect run
[4] length of 2nd zero run
.
.
.
[n-2] length of final protect run
[n-1] length of final zero run
Looking at this diagram, we see the even-numbered array elements hold the
length of the "protect" runs, and the odd-numbered elements hold the length of
the "zero" runs. If you need the first run to be a "zero" run, just include a
"protect" run of length zero as the first element of the array. If the final
run is a "protect" run, you do not need to include a zero-length "zero" run at
the end of the array. Finally, if either type of run exceeds 255 pixels,
you'll need to split this into two or more pixel runs. In this case, be sure
to include a zero-length run of the other type between the two array elements.
Example 10-23 illustrates the use of a masking map through fg_drawmask,
fg_clipmask, fg_revmask, and fg_flipmask in the standard CGA four-color
graphics mode (mode 4) to draw a black (color 0) arrow against a white
background. These four routines are respectively analogous to fg_drwimage,
fg_clpimage, fg_revimage, and fg_flpimage, but they use masking maps rather
than bitmaps. The first argument of each routine is the masking map array
(passed by reference), the second argument is the number of runs (that is, the
number of elements) in the masking map array, and the third argument is the
width in pixels of the image.
Example 10-23.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char arrow[] = {6,1,9,2,2,9,1,19,7,2,8,1};
void main()
{
int old_mode;
fg_initpm();
if (fg_testmode(4,1) == 0) {
printf("This program requires a 320 ");
printf("x 200 CGA graphics mode.\n");
exit(1);
}
250 Fastgraph User's Guide
old_mode = fg_getmode();
fg_setmode(4);
fg_setclip(0,15,0,199);
fg_setcolor(3);
fg_rect(0,319,0,199);
fg_move(10,10);
fg_drawmask(arrow,12,10);
fg_move(10,20);
fg_clipmask(arrow,12,10);
fg_move(10,30);
fg_revmask(arrow,12,10);
fg_move(10,40);
fg_flipmask(arrow,12,10);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
One of the more useful features of masking maps is their ability to clear
a portion of video memory before placing an image there. This technique
provides an efficient, simple way to include color 0 pixels in an image. It is
especially effective when displaying large or dithered images because the
masking map is typically much smaller than the bitmap required by fg_drawmap
or its related routines. Example 10-24 illustrates this process in the
standard CGA four-color graphics mode (mode 4) by displaying our arrow image
against a colored background. In this example, the arrow has a white (color 3)
perimeter and a black (color 0) interior.
The program displays the arrow in two steps. It first uses fg_drawmask to
clear the video memory where the arrow will be displayed. It then draws the
arrow's perimeter using fg_drwimage. The interior pixels in the perimeter
bitmap are transparent, but since we just zeroed that video memory, they
appear in color 0. Note we could improve this example by creating a smaller
masking map that only applies to the rectangle inscribing the arrow's
interior. That is, we don't need to zero the video memory under the arrow's
perimeter because we will immediately display other pixels there.
Example 10-24.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
char arrow_white[] = {
0x00,0x0C,0x00, 0x00,0x0F,0x00, 0xFF,0xFC,0xC0,
0xC0,0x00,0x30, 0xFF,0xFC,0xC0, 0x00,0x0F,0x00,
0x00,0x0C,0x00
};
char arrow_black[] = {6,1,9,2,2,9,1,19,7,2,8,1};
Chapter 10: Bitmapped Images 251
void main()
{
int old_mode;
fg_initpm();
if (fg_testmode(4,1) == 0) {
printf("This program requires a 320 ");
printf("x 200 CGA graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(4);
fg_setcolor(2);
fg_rect(0,319,0,199);
fg_move(10,10);
fg_drawmask(arrow_black,12,10);
fg_drwimage(arrow_white,3,7);
fg_waitkey();
fg_setmode(old_mode);
fg_reset();
}
Summary of Bitmapped Image Display Routines
This section summarizes the functional descriptions of the Fastgraph
routines presented in this chapter. More detailed information about these
routines, including their arguments and return values, may be found in the
Fastgraph Reference Manual.
For all bitmapped image routines, images are displayed or retrieved so
their lower left corner is at the graphics cursor position (or text cursor
position for those routines that also work in text video modes). In 16-bit
environments, the size of any arrays passed to these routines is limited to
64K bytes.
FG_CLIPMAP displays a clipped image stored as a mode-independent bitmap.
This routine has no effect when used in a text video mode.
FG_CLIPMASK displays a clipped image stored as a masking map. This
routine has no effect when used in a text video mode.
FG_CLPIMAGE displays a clipped image stored as a mode-specific bitmap.
Color 0 pixels are considered transparent. This routine has no effect when
used in a text video mode.
FG_DISPLAY displays an image stored in Fastgraph's standard pixel run
format, where the image resides in an array. This routine has no effect when
used in a text video mode.
252 Fastgraph User's Guide
FG_DISPLAYP displays an image stored in Fastgraph's packed pixel run
format, where the image resides in an array. This routine has no effect when
used in a text video mode.
FG_DRAWMAP displays an image stored as a mode-independent bitmap. This
routine has no effect when used in a text video mode.
FG_DRAWMASK displays an image stored as a masking map. This routine has
no effect when used in a text video mode.
FG_DRWIMAGE displays an image stored as a mode-specific bitmap. Color 0
pixels are considered transparent.
FG_FLIPMASK displays a reversed clipped image stored as a masking map.
This routine has no effect when used in a text video mode.
FG_FLPIMAGE displays a reversed clipped image stored as a mode-specific
bitmap. Color 0 pixels are considered transparent. This routine has no effect
when used in a text video mode.
FG_GETIMAGE retrieves an image as a mode-specific bitmap.
FG_GETMAP retrieves an image as a mode-independent bitmap. This routine
has no effect when used in a text video mode.
FG_IMAGESIZ determines the number of bytes required to store a mode-
specific bitmapped image of specified dimensions.
FG_INVERT inverts the row order of a mode-specific or mode-independent
bitmapped image, so a "top to bottom" image becomes a "bottom to top" image,
or vice versa.
FG_PACK converts a bitmap in the "one pixel per byte" format used in
256-color graphics modes and virtual buffers to the mode-specific bitmap
format for the current video mode.
FG_PUTIMAGE displays an image stored as a mode-specific bitmap. No
support is provided for transparent pixels.
FG_REVIMAGE displays a reversed image stored as a mode-specific bitmap.
Color 0 pixels are considered transparent. This routine has no effect when
used in a text video mode.
FG_REVMASK displays a reversed image stored as a masking map. This
routine has no effect when used in a text video mode.
FG_SCALE expands or reduces a bitmapped image stored in the "one pixel
per byte" format.
FG_SHEAR shears a bitmapped image stored in the "one pixel per byte"
format.
FG_UNPACK converts a mode-specific bitmapped image to the "one pixel per
byte" format used in 256-color graphics modes and virtual buffers.
Chapter 10: Bitmapped Images 253
FG_VBADDR returns the address of the specified virtual buffer. In 16-bit
modes, the address will be a real mode segment:offset pair or protected mode
selector:offset pair. In 32-bit modes, it will be an offset into the default
data segment.
254 Fastgraph User's Guide